AOP – Implementing Role Based Security

You may want to implement role-based security, where you only allow users assigned a certain role to perform certain actions in an application. Many different classes in your code will need role-based security added to them. As it turns out, role-based security is a cross-cutting concern. Well, Aspect Oriented Programming (AOP) can help you modular such a role-based security structure.

Lets start with an example. Maybe you have a database filled with people (people being a list of user or person objects). You want to control the list of people. Now think of the Create, Read, Update, Delete (CRUD) pattern. Now turn those into four permissions.  Any role could potentially have or not have rights to create a person, read a person’s info, update a person’s info, or delete a person.  An admin user would likely have all of the four CRUD rights. A user would likely have CRUD rights for their own user, but just read rights for other users. Your design might have multiple levels of rights as well. You may want to provide multiple levels of read permissions. Think of any social network where you have more read rights if you are a friend of another Person.

If it was just for a Person object, you probably would implement an AOP-based solution. However, a large application will have dozens of classes around the Person class. It will have many entities besides Person and those entities have many surrounding data classes as well. What if you had to add code to over 100 class objects? Now you can really benefit from an AOP-based design.

Well, I am going to show you example to help get you started.
Lets say you want to encrypt a field of a class. You might think that this is not a crosscutting concern, but it is. What if throughout and entire solution you need to encrypt random fields in many of your classes. Adding encryption to each of the classes can be a significant burden and breaks the “single responsibility principle” by having many classes implementing encryption. Of course, a static method or a single might be used to help, but even with that, code is must be added to each class. With Aspect Oriented Programming, this encryption could happen in one Aspect file, and be nice and modular.

Prereqs

This example assumes you have a development environment installed with at least the following:

  • JDK
  • AspectJ
  • Eclipse (Netbeans would work too)

Step 1 – Create an AspectJ project

  1. In Eclipse, choose File | New | Project.
  2. Select AspectJ | AspectJ Project.
  3. Click Next.
  4. Name your project.
    Note: I named my project AOPRolePermissions
  5. Click Finish.
The project is now created.

Step 2 – Create a class containing main()

  1. Right-click on the project in Package Explorer and choose New | Class.
  2. Provide a package name.
    Note: I named my package the same as the project name.
  3. Give the class a name.
    Note: I often name my class Main.
  4. Check the box to include a public static void main(String[] args) method.
  5. Click Finish.
package AOPRolePermissions;

public class Main
{
	public static void main(String[] args)
	{
		// TODO Auto-generated method stub
	}
}

Step 3 – Create an object that needs Role-based security

For this example, I am going to use a simple Person object.

  1. Right-click on the package in Package Explorer and choose New | Class.
    Note: The package should already be filled out for you.
  2. Give the class a name.
    Note: I named mine Person.
  3. Click Finish.
  4. Add String fields for FirstName and LastName.
  5. Add a getter and setter for each.
package AOPRolePermissions;

public class Person
{
	// First Name
	private String FirstName = "";

	public String getFirstName()
	{
		return FirstName;
	}

	public void setFirstName(String inFirstName)
	{
		FirstName = inFirstName;
	}

	// Last Name
	private String LastName = "";

	public String getLastName()
	{
		return LastName;
	}

	public void setLastName(String inLastName)
	{
		LastName = inLastName;
	}
}

a

Step 4 – Implement example role-based code

For this I created the following objects:

  • Role
  • Permission
  • Permissions
  • FakeSession

The implementation of these is not important to this article, so I am not posting their code. However, you will see these classes if you download the project.

Step 5 – Implement an Annotation for  Role-based Security

Lets add an annotation to mark methods that should use role-based security.

  1. Right-click on the package in Package Explorer and choose New | Annotation.
    Note: The package should already be filled out for you.
  2. Give the annotation a name.
    Note: I named mine RoleBasedSecurity.
  3. Click Finish.
  4. Add a value for the permission type.
  5. Add a value for the Field name (in case the method is named completely different from the field).
  6. Set the Retention to RetentionPolicy.RUNTIME.
  7. Maybe add a comment that this annotation is for use by the Aspect (which we will create shortly).
package AOPRolePermissions;

import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;

@Retention(RetentionPolicy.RUNTIME)
public @interface RoleBasedSecurity
{
	Permission.Type value() default Permission.Type.All;
	String FieldName() default "";
}

Step 6 – Add the @RoleBasedSecurity annotation to methods

  1. In the Person class, add @RoleBasedSecurity(Type.Read) tag above the gettersof Person.
  2. In the Person class, add @RoleBasedSecurity(Type.Update) tag above the setters of Person.
package AOPRolePermissions;

import AOPRolePermissions.Permission.Type;

public class Person
{
	// First Name
	private String FirstName = "";

	@RoleBasedSecurity(value = Type.Read)
	public String getFirstName()
	{
		return FirstName;
	}

	@RoleBasedSecurity(Type.Update)
	public void setFirstName(String inFirstName)
	{
		FirstName = inFirstName;
	}

	// Last Name
	private String LastName = "";

	@RoleBasedSecurity(value = Type.Read)
	public String getLastName()
	{
		return LastName;
	}

	@RoleBasedSecurity(Type.Update)
	public void setLastName(String inLastName)
	{
		LastName = inLastName;
	}
}

Step 7 – Create an Aspect to check Role-based permissions

  1. Right-click on the package in Package Explorer and choose New | Other.
  2. Choose AspectJ | Aspect.
  3. Click Next.
    Note: The package should already be filled out for you.
  4. Give the Aspect a name.
    Note: I named mine SecureByRoleAspect.
  5. Click Finish.
package AOPRolePermissions;

public aspect SecureByRoleAspect
{

}

Step 7 – Add the pointcut and advice

  1. Add a pointcut called RoleBasedSecurityMethod.
  2. Implement it to work for any method called that is annotated with @RoleBasedSecurity: call(@RoleBasedSecurity * *(..)).
  3. Add a !within(SecureByRoleAspect) (to prevent an infinite loop).
package AOPEncryptionExample;

public aspect EncryptFieldAspect
{
	pointcut RoleBasedSecurityMethod() : call(@RoleBasedSecurity * *(..)) && !within(SecureByRoleAspect);
}

You now have your pointcut.

Step 8 – Implement around advice to check for permissions

  1. Add around advice that returns an Object.
  2. Implement it to be for the RoleBasedSecurityMethod pointcut.
  3. Add code to check for permissions.
  4. Add a return statement.
package AOPRolePermissions;

import java.lang.reflect.Method;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.reflect.MethodSignature;

public aspect SecureByRoleAspect
{
	pointcut RoleBasedSecurityMethod() : call(@RoleBasedSecurity * *(..))	
									&& !within(SecureByRoleAspect);
	
	
	Object around() : RoleBasedSecurityMethod()
	{
		System.out.println("Checking permissions...");
		
		RoleBasedSecurity rbs = getRBSAnnotation(thisJoinPointStaticPart);

		// Use the FieldName if specified, otherwise guess it from the method name
		String field = (rbs.FieldName().equals("")) ? removeLowerCasePrefix(thisJoinPointStaticPart
				.getSignature().getName()) : rbs.FieldName();

		if (FakeSession.Instance.getCurrentRole().GetPermissions()
				.can(rbs.value(), field))
		{
			System.out.println(String.format(
					"Success: Role has permissions to %s field named %s.%s.",
					rbs.value(), thisJoinPointStaticPart.getSignature()
							.getDeclaringType().getName(), field));
			return proceed();
		}
		else
		{
			System.out
					.println(String
							.format("Failure: Role has insufficient permissions to %s field named %s.%s.",
									rbs.value(), thisJoinPointStaticPart
											.getSignature().getDeclaringType()
											.getName(), field));
		}

		return null;
	}

	private String removeLowerCasePrefix(String inString)
	{
		int startPoint = 0;
		for (int i = 0; i < inString.length(); i++)
		{
			if (Character.isUpperCase(inString.charAt(i)))
			{
				startPoint = i;
				break;
			}
		}
		return inString.substring(startPoint);
	}

	private RoleBasedSecurity getRBSAnnotation(JoinPoint.StaticPart inStaticPart)
	{
		RoleBasedSecurity rbs = null;
		Signature sig = inStaticPart.getSignature();
		if (sig instanceof MethodSignature)
		{
			// this must be a call or execution join point
			Method method = ((MethodSignature) sig).getMethod();
			rbs = method.getAnnotation(RoleBasedSecurity.class);
		}
		return rbs;
	}
}

You are done. Go ahead and run the program. You should get the following output.

Checking permissions...
Success: Role has permissions to Update field named AOPRolePermissions.Person.FirstName.
Checking permissions...
Success: Role has permissions to Update field named AOPRolePermissions.Person.LastName.
Checking permissions...
Success: Role has permissions to Read field named AOPRolePermissions.Person.FirstName.
John
Checking permissions...
Success: Role has permissions to Read field named AOPRolePermissions.Person.LastName.
Johnson
Checking permissions...
Failure: Role has insufficient permissions to Update field named AOPRolePermissions.Person.FirstName.
Checking permissions...
Failure: Role has insufficient permissions to Update field named AOPRolePermissions.Person.LastName.
Checking permissions...
Success: Role has permissions to Read field named AOPRolePermissions.Person.FirstName.
John
Checking permissions...
Success: Role has permissions to Read field named AOPRolePermissions.Person.LastName.
Johnson

Role Based Security with AOP Project Download

AOPRolePermissions.zip

Return to Aspected Oriented Programming – Examples

One Comment

  1. [...] – Implementing Role Based Security Filed under: FreeBSD — rhyous @ 12:31 am Read more Share this:DiggRedditLike this:LikeBe the first to like this post. Leave a [...]

Leave a Reply

How to post code in comments?